package edu.pku.sei.transformation.editor.model;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.common.MetaTypedList;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.transformation.editor.model.pattern.ILinkTemplate;
import edu.pku.sei.transformation.editor.model.pattern.INodeTemplate;
import edu.pku.sei.transformation.editor.model.pattern.Pattern;
import edu.pku.sei.transformation.editor.parser.texttemplate.TemplateParser;
import edu.pku.sei.transformation.editor.parser.texttemplate.element.ElementEdge;
import edu.pku.sei.transformation.editor.parser.texttemplate.element.StructuredTextElement;
import edu.pku.sei.transformation.editor.parser.texttemplate.element.TextElement;
import edu.pku.sei.transformation.editor.parser.texttemplate.element.TextElementRegister;
import edu.pku.sei.transformation.editor.parser.texttemplate.equivalence.EquivalenceNode;

public class Comment extends MetaModelElement implements INodeTemplate {
	// INodeTemplate
	private MetaTypedList incoming;
	private MetaTypedList outgoing;
	private Pattern pattern;

	private String content = "";
	
	private TextElementRegister register;
	
	@MethodProperty(name = "content", id = ModelPackage.LITERAL_CONTENT, catalog = "comment", setter = "setContent")
	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		String oldValue = this.content;
		this.content = content;
		firePropertyChange(ModelPackage.LITERAL_CONTENT, oldValue, content);
		TemplateParser parser = new TemplateParser();
		register = parser.parse(content);
		if (register != null)
			register.getRoot().setEquivalenceNode(new EquivalenceNode(register));
	}

	@Override
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeAttribute(root,
				ModelPackage.LITERAL_CONTENT, content);
	}

	@Override
	public void deSerialize(Element root) {
		super.deSerialize(root);
		this.content = XMLUtility.xmlInstance.deSerializeString(root,
				ModelPackage.LITERAL_CONTENT);
		TemplateParser parser = new TemplateParser();
		register = parser.parse(content);
		if (register != null)
			register.getRoot().setEquivalenceNode(new EquivalenceNode(register));
	}

	@Override
	public Pattern getPattern() {
		if (pattern == null && getContainer() != null
				&& getContainer() instanceof Pattern) {
			pattern = (Pattern) getContainer();
		}
		return pattern;
	}

	@Override
	public void setPattern(Pattern owner) {
		this.pattern = owner;
	}

	public MetaTypedList getIncoming() {
		if (incoming == null)
			incoming = new MetaTypedList(ILinkTemplate.class, this,
					ModelPackage.NODE_TEMPLATE_INCOMING);
		return incoming;
	}

	public MetaTypedList getOutgoing() {
		if (outgoing == null)
			outgoing = new MetaTypedList(ILinkTemplate.class, this,
					ModelPackage.NODE_TEMPLATE_OUTGOING);
		return outgoing;
	}
	
	public List<StructuredTextElement> getStructuralElement() {
		List<StructuredTextElement> result = new ArrayList<StructuredTextElement>();
		if (register != null) {
			for (TextElement element : register.getAllElements()) {
				if (element instanceof StructuredTextElement)
					result.add((StructuredTextElement) element);
			}
		}
		return result;
	}
	
	public List<TextElement> getAllNodes() {
		if (register != null)
			return register.getAllElements();
		else
			return new ArrayList<TextElement>();
	}
	
	public List<ElementEdge> getAllLinks() {
		if (register != null) 
			return register.getAllEdges();
		else 
			return new ArrayList<ElementEdge>();
	}
	
	public TextElementRegister getRegister() {
		return register;
	}
	
	public GraphicalDomain getDomain() {
		if (getPattern() != null) {
			return (GraphicalDomain) getPattern().getOwner();
		}
		return null;
	}
}
